package client

import (
	"chess_platform/internal/apple_pay"
	. "chess_platform/internal/common"
	"chess_platform/internal/login/fetch"
	"chess_platform/models/client"
	"chess_platform/modules"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"
)

//[client]支付相关
type PayController struct {
	GrantController
}

func (b *PayController) URLMapping() {
	b.Mapping("PayType", b.PayType)
	b.Mapping("ListProduct", b.ListProduct)
	b.Mapping("ListDiamondCoin", b.ListDiamondCoin)
	b.Mapping("ExchangeDiamondCoin", b.ExchangeDiamondCoin)
	b.Mapping("AppleCallBack", b.AppleCallBack)
	b.Mapping("PreOrder", b.PreOrder)               //包含爱贝APP支付
	b.Mapping("IPayCreateOrder", b.IPayCreateOrder) //爱贝H5支付
	b.Mapping("QueryOrder", b.QueryOrder)
}

// @Title 获取支付方式
// @Description 获取支付方式
// @Success 0 {string} 返回支付方式的id,1-爱贝,2-贝付宝
// @router /pay-type [post]
func (b *PayController) PayType() {
	payType := modules.GetPayTypeByPlatform(PlatformClient)
	if payType == 0 {
		LogClient.Error("获取支付方式失败,用默认的支付方式返回给前端")
		b.Res.Data = PayTypeIPay
	} else {
		b.Res.Data = payType
	}

	b.ResponseSuccess()
}

// @Title 商城商品列表
// @Description 商城商品列表
// @Success 0 {object} []common.Store
// @router /list-product [post]
func (b *PayController) ListProduct() {
	store, err := client.ListProduct()
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = store
	b.ResponseSuccess()
}

// @Title 钻石兑换金币列表
// @Description 钻石兑换金币列表
// @Success 0 {object} []common.DiamondCoin
// @router /list-diamond-coin [post]
func (b *PayController) ListDiamondCoin() {
	store, err := client.ListDiamondCoin()
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = store
	b.ResponseSuccess()
}

// @Title 钻石兑换金币
// @Description 钻石兑换金币
// @Param   id             body    int true      "id"
// @Success 0 {object} []common.DiamondCoin
// @router /exchange-diamond-coin [post]
func (b *PayController) ExchangeDiamondCoin() {
	type Params struct {
		Id int64 `json:"id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	dc, err := client.DiamondCoinById(p.Id)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if dc == nil {
		b.ResponseFail("此兑换不存在")
		return
	}
	ok := client.ChangeAccountValueFromLobby(b.Uid, -dc.Diamond,
		dc.Coin, 0, ACCTRAN_OPER_TYPE_Exchange, 0)
	if !ok {
		b.ResponseFail("系统繁忙,兑换失败,请稍后重试")
		return
	}
	b.ResponseSuccess("兑换成功")
}

const (
	AppleTestVerifyUrl = "https://sandbox.itunes.apple.com/verifyReceipt"
	AppleProVerifyUrl  = "https://buy.itunes.apple.com/verifyReceipt"
)

// @Title 苹果支付回调接口
// @Description 苹果支付回调接口
// @Param   ios_version   	  body    string  true      "ios版本"
// @Param   order_id          body    int     true      "平台订单号"
// @Param   receipt           body    string  true      "receipt data"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /apple-callback [post]
func (b *PayController) AppleCallBack() {
	type Params struct {
		IosVersion float64 `json:"ios_version"`
		OrderId    int64   `json:"order_id"`
		Receipt    string  `json:"receipt" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	msg, _ := base64.StdEncoding.DecodeString(p.Receipt)
	LogClient.Debug(fmt.Sprintf("客户端传来原数据base64解析之后:%#v\n", string(msg)))

	requestData := map[string]interface{}{
		"receipt-data": p.Receipt,
	}
	body, err := json.Marshal(requestData)
	if err != nil {
		LogClient.Error(b.SystemError(err.Error()))
		return
	}
	var productId int64      //苹果产品id
	var transactionId string //苹果订单号
	//提交到苹果正式服务器验证
	proUrl := fmt.Sprintf("%v", AppleProVerifyUrl)
	rsp, err := fetch.Cmd(fetch.Request{
		Method: "POST",
		URL:    proUrl,
		Body:   body,
		Header: http.Header{"Content-Type": {"application/json"}},
	})
	if err != nil {
		LogClient.Error(b.SystemError(err.Error()))
		return
	}
	LogClient.Debug(fmt.Sprintf("苹果正式服务器返回值:%#v\n", string(rsp)))
	r, err := apple_pay.Verify(rsp)
	if err != nil {
		LogClient.Error(fmt.Sprintf("解析出错:%#v\n", err))
		b.ResponseFail("系统异常")
		return
	}
	//提交到苹果测试服务器验证
	if r.Status == 21007 || r.Receipt.Status == 21007 {
		testUrl := fmt.Sprintf("%v", AppleTestVerifyUrl)
		rsp, err := fetch.Cmd(fetch.Request{
			Method: "POST",
			URL:    testUrl,
			Body:   body,
			Header: http.Header{"Content-Type": {"application/json"}},
		})
		if err != nil {
			LogClient.Error(b.SystemError(err.Error()))
			return
		}
		LogClient.Debug(fmt.Sprintf("苹果测试服务器返回值:%#v\n", string(rsp)))
		r, err := apple_pay.Verify(rsp)
		if err != nil {
			LogClient.Error(fmt.Sprintf("解析出错:%#v\n", err))
			b.ResponseFail("系统异常")
			return
		}
		if r.Receipt.Status != 0 {
			LogClient.Error(fmt.Sprintf("苹果测试服务器返回错误,错误码:%v\n", r.Receipt.Status))
			b.ResponseFail("系统异常")
			return
		}
		productId, _ = strconv.ParseInt(r.Receipt.ProductId, 10, 64)
		transactionId = r.Receipt.TransactionId
	} else if r.Status != 0 || r.Receipt.Status != 0 {
		LogClient.Error(fmt.Sprintf("苹果正式服务器返回错误,第一错误码:%v\n", r.Status))
		LogClient.Error(fmt.Sprintf("苹果正式服务器返回错误,第二错误码:%v\n", r.Receipt.Status))
		b.ResponseFail("系统异常")
		return
	} else {
		productId, _ = strconv.ParseInt(r.Receipt.ProductId, 10, 64)
		transactionId = r.Receipt.TransactionId
	}
	LogClient.Debug(fmt.Sprintf("苹果返回的商品id:%v", productId))
	order, err := client.OrderById(p.OrderId)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	//订单不存在
	if order == nil {
		b.ResponseFail("订单不存在")
		return
	}
	product, err := client.ProductByAppleProductId(productId)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if product.Num != order.Num && product.Amount != order.Amount {
		LogClient.Error("平台订单发货数量及金额与苹果商品id对应的发货数量及金额对不上,这一个伪造的平台订单")
		b.ResponseFail("订单异常")
		return
	}

	if order.TransactionId != "" && order.TransactionId != transactionId {
		LogClient.Error("平台里记录的苹果订单号与苹果服务器返回的苹果订单号不一样,这一个伪造的平台订单")
		b.ResponseFail("订单异常")
		return
	}

	//此订单已是成功发货的了，说明是重复通知了
	if order.Status == OrderDelivered {
		b.ResponseSuccess("已发货,无需再次发货")
		return
	}
	//支付成功
	updateData := map[string]interface{}{
		"transaction_id": transactionId,
		"status":         OrderPaySuccess,
		"pay_time":       time.Now().Unix(),
	}
	_, err = client.UpdateOrder(updateData, p.OrderId)
	if err != nil {
		LogClient.Error(err.Error())
		return
	}
	//发货
	if err := modules.DeliveryDiamond(order.Uid, order.Num, order.Id); err != nil {
		LogClient.Error(fmt.Sprintf("玩家(ID:%v)商城购买钻石发货失败", order.Uid))
		b.ResponseFail("发货失败,请联系客服")
		return
	}
	b.ResponseSuccess("购买成功")
}

// @Title H5预支付(爱贝H5支付)
// @Description H5预支付(爱贝H5支付)
// @Param   id             body    int true      "购买钻石数量对应的id"
// @Param   pay_type       body    int true      "支付类型,2-微信支付,3-支付宝支付"
// @Param   url_r          body    int true      "支付成功回调url"
// @Param   url_h          body    int true      "支付取消回调url"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /ipay-create-order [post]
func (b *PayController) IPayCreateOrder() {
	type Params struct {
		Id      int64  `json:"id" valid:"Required"`
		PayType int64  `json:"pay_type" valid:"Range(2,3)"`
		UrlR    string `json:"url_r" valid:"Required"`
		UrlH    string `json:"url_h" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	//找出买多少张，多少钱
	product, err := client.ProductById(p.Id)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if product.Id == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = "您购买的商品不存在"
		b.Response()
		return
	}
	order := map[string]interface{}{
		"pay_type":   p.PayType,
		"uid":        b.Uid, //玩家id
		"amount":     product.Amount,
		"num":        product.Num,
		"status":     OrderNotPay,
		"order_time": time.Now().Unix(),
	}
	orderId, err := client.PreOrder(order)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}

	notifyUrl := BasePayCallBack + "/v1/client/public/ipay-callback"
	orderIdStr := fmt.Sprintf("%v%v", ClientIPayPre, orderId)
	price := float32(product.Amount) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
	transId, err := H5IPay.CreateIpayOrder(1, "", orderIdStr, price, "xiashen", "", notifyUrl)
	if err != nil {
		LogClient.Error(b.SystemError(err.Error()))
		return
	}
	updateData := map[string]interface{}{
		"transaction_id": transId,
	}
	_, err = client.UpdateOrder(updateData, orderId)
	if err != nil {
		LogClient.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
	}

	payUrl, err := H5IPay.GetHtml5PayUrl(transId, p.UrlR, p.UrlH, IPayPayType(p.PayType))
	if err != nil {
		LogClient.Error(b.SystemError(err.Error()))
		return
	}
	b.Res.Data = payUrl
	b.ResponseSuccess()
}

// @Title 预订单(苹果支付预订单)
// @Description 预订单(苹果支付预订单)
// @Param   id             body    int true      "商品id"
// @Param   pay_type       body    int true      "支付类型,1-苹果，2-微信,3-支付宝,4-爱贝"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /pre-order [post]
func (b *PayController) PreOrder() {
	type Params struct {
		Id      int64 `json:"id" valid:"Required"`
		PayType int64 `json:"pay_type" valid:"Range(1,4)"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	//找出买多少张，多少钱
	product, err := client.ProductById(p.Id)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if product.Id == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = "您购买的商品不存在"
		b.Response()
		return
	}
	order := map[string]interface{}{
		"pay_type":   p.PayType,
		"uid":        b.Uid, //玩家id
		"amount":     product.Amount,
		"num":        product.Num,
		"status":     OrderNotPay,
		"order_time": time.Now().Unix(),
	}
	orderId, err := client.PreOrder(order)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	switch p.PayType {
	case ApplePay:
		b.Res.Data = map[string]interface{}{
			"order_id":   orderId,
			"product_id": product.ProductId,
		}
	case IPayPay:
		notifyUrl := BasePayCallBack + "/v1/client/public/ipay-callback"
		orderIdStr := fmt.Sprintf("%v%v", ClientIPayPre, orderId)
		price := float32(product.Amount) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
		privateInfo := fmt.Sprintf("购买数量:%v", product.Num)
		transId, err := ClientIPay.CreateIpayOrder(1, "", orderIdStr, price,
			"xiashen", privateInfo, notifyUrl)
		if err != nil {
			LogClient.Error(b.SystemError(err.Error()))
			return
		}
		updateData := map[string]interface{}{
			"transaction_id": transId,
		}
		_, err = client.UpdateOrder(updateData, orderId)
		if err != nil {
			LogClient.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
		}
		b.Res.Data = map[string]interface{}{
			"order_id": transId,
		}
	case WeChatPay:
	case AliPay:

	}
	b.ResponseSuccess()

}

// @Title 查询订单支付情况
// @Description 查询订单支付情况
// @Param   order_id         body    int true      "订单id"
// @Success 0 {string} 订单状态
// @Failure 400
// @Failure 404
// @router /query-order [post]
func (b *PayController) QueryOrder() {
	type Params struct {
		OrderId int64 `json:"order_id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	order, err := client.OrderById(p.OrderId)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if order == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrOrderNoExist
		b.Response()
		return
	}
	b.Res.Data = order.Status
	b.ResponseSuccess()
}
